package com.fy.fyspace.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fy.fyspace.common.result.R;
import com.fy.fyspace.common.utils.ImageUtil;
import com.fy.fyspace.constant.KeysConstant;
import com.fy.fyspace.mapper.FavoritePictureMapper;
import com.fy.fyspace.mapper.PictureMapper;
import com.fy.fyspace.model.entity.FavoritePicture;
import com.fy.fyspace.model.entity.Picture;
import com.fy.fyspace.model.enums.picture.PictureDeleteStatusEnum;
import com.fy.fyspace.model.vo.picture.PictureVO;
import com.fy.fyspace.model.vo.user.UserSessionVO;
import com.fy.fyspace.service.FavoritePictureService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import static com.fy.fyspace.common.result.R.no;
import static com.fy.fyspace.common.result.R.ok;
import static org.springframework.beans.BeanUtils.copyProperties;

/**
 * <p>
 * 图片 服务实现类
 * </p>
 *
 * @author fwq
 * @since 2025-06-25
 */
@Slf4j
@Service
public class FavoritePictureServiceImpl extends ServiceImpl<FavoritePictureMapper, FavoritePicture> implements FavoritePictureService {

    @Resource
    private HttpSession httpSession;

    @Resource
    private FavoritePictureMapper favoritePictureMapper;

    @Resource
    private PictureMapper pictureMapper;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource(name = "batchOperationThreadPool")
    private ThreadPoolExecutor batchOperationThreadPool;

    // 批量操作阈值 - 超过此数量使用线程池
    private static final int BATCH_THRESHOLD = 10;

    private void deleteAllPictureCache() {
        // 假设首页最大100页，pageSize为30和40都处理
        for (int page = 1; page <= 100; page++) {
            for (int pageSize : new int[]{30, 40}) {
                String cacheKey = "picture:data" + String.format("default:%d:%d", page, pageSize);
                redisTemplate.delete(cacheKey);
            }
        }
    }

    /**
     * 批量收藏图片
     * @param picIds
     * @return
     */
    @Override
    @Transactional
    public R batchFavoritePictures(String picIds) {
        UserSessionVO userSessionVO = (UserSessionVO) httpSession.getAttribute(KeysConstant.LOGIN_SESSION_KEY);
        if (StringUtils.isBlank(picIds)) {
            return no("图片ID不能为空");
        }
        
        String[] picIdArr = picIds.split(",");
        Set<Long> picIdSet = Arrays.stream(picIdArr)
                .filter(StringUtils::isNotBlank)
                .map(Long::parseLong)
                .collect(Collectors.toSet());

        log.info("开始批量收藏图片，总数：{}，用户ID：{}", picIdSet.size(), userSessionVO.getId());

        // 如果图片数量超过阈值，使用线程池并发处理
        if (picIdSet.size() > BATCH_THRESHOLD) {
            return batchFavoritePicturesWithThreadPool(picIdSet, userSessionVO.getId());
        } else {
            // 小批量直接处理
            return batchFavoritePicturesSequentially(picIdSet, userSessionVO.getId());
        }
    }

    /**
     * 使用线程池并发批量收藏图片
     */
    private R batchFavoritePicturesWithThreadPool(Set<Long> picIdSet, Long userId) {
        long startTime = System.currentTimeMillis();
        log.info("使用线程池并发处理批量收藏，图片数量：{}，线程池状态：活跃线程={}，队列大小={}",
                picIdSet.size(), batchOperationThreadPool.getActiveCount(), batchOperationThreadPool.getQueue().size());

        List<CompletableFuture<Void>> futures = new ArrayList<>();
        AtomicInteger successCount = new AtomicInteger(0);
        AtomicInteger skipCount = new AtomicInteger(0);
        AtomicInteger errorCount = new AtomicInteger(0);

        for (Long picId : picIdSet) {
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                try {
                    processSingleFavorite(picId, userId, successCount, skipCount, errorCount);
                } catch (Exception e) {
                    log.error("处理图片收藏失败，picId：{}，错误：{}", picId, e.getMessage());
                    errorCount.incrementAndGet();
                }
            }, batchOperationThreadPool);
            
            futures.add(future);
        }

        // 等待所有任务完成
        try {
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).get(30, TimeUnit.SECONDS);
        } catch (Exception e) {
            log.error("批量收藏操作超时或异常：{}", e.getMessage());
            return no("批量收藏操作超时，请稍后重试");
        }

        long endTime = System.currentTimeMillis();
        log.info("批量收藏完成，耗时：{}ms，成功：{}，跳过：{}，失败：{}",
                (endTime - startTime), successCount.get(), skipCount.get(), errorCount.get());

        // 清除缓存
        deleteAllPictureCache();

        return ok(String.format("批量收藏完成，成功：%d，跳过：%d，失败：%d，耗时：%dms",
                successCount.get(), skipCount.get(), errorCount.get(), (endTime - startTime)));
    }

    /**
     * 串行批量收藏图片
     */
    private R batchFavoritePicturesSequentially(Set<Long> picIdSet, Long userId) {
        long startTime = System.currentTimeMillis();
        int successCount = 0;
        int skipCount = 0;
        int errorCount = 0;

        for (Long picId : picIdSet) {
            try {
                AtomicInteger tempSuccess = new AtomicInteger(0);
                AtomicInteger tempSkip = new AtomicInteger(0);
                AtomicInteger tempError = new AtomicInteger(0);
                
                processSingleFavorite(picId, userId, tempSuccess, tempSkip, tempError);
                
                successCount += tempSuccess.get();
                skipCount += tempSkip.get();
                errorCount += tempError.get();
            } catch (Exception e) {
                log.error("处理图片收藏失败，picId：{}，错误：{}", picId, e.getMessage());
                errorCount++;
            }
        }

        long endTime = System.currentTimeMillis();
        log.info("串行批量收藏完成，耗时：{}ms，成功：{}，跳过：{}，失败：{}",
                (endTime - startTime), successCount, skipCount, errorCount);

        // 清除缓存
        deleteAllPictureCache();

        return ok(String.format("批量收藏完成，成功：%d，跳过：%d，失败：%d，耗时：%dms",
                successCount, skipCount, errorCount, (endTime - startTime)));
    }

    /**
     * 处理单个图片收藏
     */
    private void processSingleFavorite(Long picId, Long userId, AtomicInteger successCount, 
                                     AtomicInteger skipCount, AtomicInteger errorCount) {
        log.info("[DEBUG] 当前处理picId={}, 类型={}，userId={}, 类型={}", 
                picId, picId.getClass(), userId, userId.getClass());
        
        FavoritePicture favorite = favoritePictureMapper.selectAllStatusByPicIdAndUserId(picId, userId);
        log.info("[DEBUG] 查询FavoritePicture结果: {}", favorite);
        
        Picture picture = pictureMapper.selectById(picId);
        if (picture == null) {
            log.warn("图片不存在，picId：{}", picId);
            errorCount.incrementAndGet();
            return;
        }

        if (favorite == null) {
            // 没有记录，插入新收藏
            FavoritePicture newFavorite = new FavoritePicture();
            copyProperties(picture, newFavorite);
            Integer favoriteCount = (picture.getFavoriteCount() == null ? 1 : picture.getFavoriteCount() + 1);
            newFavorite.setId(null);
            newFavorite.setPicId(picture.getId());
            newFavorite.setCreateTime(new Date());
            newFavorite.setUpdateTime(new Date());
            newFavorite.setIsDelete(PictureDeleteStatusEnum.NOT_DELETE.getValue());
            newFavorite.setCreateUserId(picture.getUserId());
            newFavorite.setFavoriteUserId(userId);
            favoritePictureMapper.insert(newFavorite);
            picture.setFavoriteCount(favoriteCount);
            pictureMapper.updateById(picture);
            successCount.incrementAndGet();
            log.info("新增收藏成功，picId：{}", picId);
        } else if (favorite.getIsDelete() != null && favorite.getIsDelete().equals(PictureDeleteStatusEnum.IS_DELETE.getValue())) {
            // 恢复收藏
            favoritePictureMapper.updateStatus(favorite.getId(), PictureDeleteStatusEnum.NOT_DELETE.getValue(), new Date());
            Integer favoriteCount = (picture.getFavoriteCount() == null ? 1 : picture.getFavoriteCount() + 1);
            picture.setFavoriteCount(favoriteCount);
            pictureMapper.updateById(picture);
            successCount.incrementAndGet();
            log.info("恢复收藏成功，picId：{}", picId);
        } else if (favorite.getIsDelete() != null && favorite.getIsDelete().equals(PictureDeleteStatusEnum.NOT_DELETE.getValue())) {
            // 已收藏，跳过
            skipCount.incrementAndGet();
            log.info("已收藏，跳过: favoriteId={}, picId={}", favorite.getId(), picId);
        }
    }

    /**
     * 批量取消收藏图片
     * @param picIds
     * @return
     */
    @Override
    @Transactional
    public R batchCancelFavoritePictures(String picIds) {
        UserSessionVO userSessionVO = (UserSessionVO) httpSession.getAttribute(KeysConstant.LOGIN_SESSION_KEY);
        if (StringUtils.isBlank(picIds)) {
            return no("图片ID不能为空");
        }
        
        String[] picIdArr = picIds.split(",");
        Set<Long> picIdSet = Arrays.stream(picIdArr)
                .filter(StringUtils::isNotBlank)
                .map(Long::parseLong)
                .collect(Collectors.toSet());

        log.info("开始批量取消收藏图片，总数：{}，用户ID：{}", picIdSet.size(), userSessionVO.getId());

        // 如果图片数量超过阈值，使用线程池并发处理
        if (picIdSet.size() > BATCH_THRESHOLD) {
            return batchCancelFavoritePicturesWithThreadPool(picIdSet, userSessionVO.getId());
        } else {
            // 小批量直接处理
            return batchCancelFavoritePicturesSequentially(picIdSet, userSessionVO.getId());
        }
    }

    /**
     * 使用线程池并发批量取消收藏图片
     */
    private R batchCancelFavoritePicturesWithThreadPool(Set<Long> picIdSet, Long userId) {
        long startTime = System.currentTimeMillis();
        log.info("使用线程池并发处理批量取消收藏，图片数量：{}，线程池状态：活跃线程={}，队列大小={}",
                picIdSet.size(), batchOperationThreadPool.getActiveCount(), batchOperationThreadPool.getQueue().size());

        List<CompletableFuture<Void>> futures = new ArrayList<>();
        AtomicInteger successCount = new AtomicInteger(0);
        AtomicInteger skipCount = new AtomicInteger(0);
        AtomicInteger errorCount = new AtomicInteger(0);

        for (Long picId : picIdSet) {
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                try {
                    processSingleCancelFavorite(picId, userId, successCount, skipCount, errorCount);
                } catch (Exception e) {
                    log.error("处理图片取消收藏失败，picId：{}，错误：{}", picId, e.getMessage());
                    errorCount.incrementAndGet();
                }
            }, batchOperationThreadPool);
            
            futures.add(future);
        }

        // 等待所有任务完成
        try {
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).get(30, TimeUnit.SECONDS);
        } catch (Exception e) {
            log.error("批量取消收藏操作超时或异常：{}", e.getMessage());
            return no("批量取消收藏操作超时，请稍后重试");
        }

        long endTime = System.currentTimeMillis();
        log.info("批量取消收藏完成，耗时：{}ms，成功：{}，跳过：{}，失败：{}",
                (endTime - startTime), successCount.get(), skipCount.get(), errorCount.get());

        // 清除缓存
        deleteAllPictureCache();

        return ok(String.format("批量取消收藏完成，成功：%d，跳过：%d，失败：%d，耗时：%dms",
                successCount.get(), skipCount.get(), errorCount.get(), (endTime - startTime)));
    }

    /**
     * 串行批量取消收藏图片
     */
    private R batchCancelFavoritePicturesSequentially(Set<Long> picIdSet, Long userId) {
        long startTime = System.currentTimeMillis();
        int successCount = 0;
        int skipCount = 0;
        int errorCount = 0;

        for (Long picId : picIdSet) {
            try {
                AtomicInteger tempSuccess = new AtomicInteger(0);
                AtomicInteger tempSkip = new AtomicInteger(0);
                AtomicInteger tempError = new AtomicInteger(0);
                
                processSingleCancelFavorite(picId, userId, tempSuccess, tempSkip, tempError);
                
                successCount += tempSuccess.get();
                skipCount += tempSkip.get();
                errorCount += tempError.get();
            } catch (Exception e) {
                log.error("处理图片取消收藏失败，picId：{}，错误：{}", picId, e.getMessage());
                errorCount++;
            }
        }

        long endTime = System.currentTimeMillis();
        log.info("串行批量取消收藏完成，耗时：{}ms，成功：{}，跳过：{}，失败：{}",
                (endTime - startTime), successCount, skipCount, errorCount);

        // 清除缓存
        deleteAllPictureCache();

        return ok(String.format("批量取消收藏完成，成功：%d，跳过：%d，失败：%d，耗时：%dms",
                successCount, skipCount, errorCount, (endTime - startTime)));
    }

    /**
     * 处理单个图片取消收藏
     */
    private void processSingleCancelFavorite(Long picId, Long userId, AtomicInteger successCount, 
                                           AtomicInteger skipCount, AtomicInteger errorCount) {
        log.info("[DEBUG] 当前处理picId={}, 类型={}，userId={}, 类型={}", 
                picId, picId.getClass(), userId, userId.getClass());
        
        FavoritePicture favorite = favoritePictureMapper.selectAllStatusByPicIdAndUserId(picId, userId);
        log.info("[DEBUG] 查询FavoritePicture结果: {}", favorite);
        
        if (favorite == null) {
            log.warn("未找到收藏记录: userId={}, picId={}", userId, picId);
            skipCount.incrementAndGet();
            return;
        }

        if (favorite.getIsDelete() != null && favorite.getIsDelete().equals(PictureDeleteStatusEnum.NOT_DELETE.getValue())) {
            // 执行取消收藏
            favoritePictureMapper.updateStatus(favorite.getId(), PictureDeleteStatusEnum.IS_DELETE.getValue(), new Date());
            
            // 更新图片表 favoriteCount
            Picture picture = pictureMapper.selectById(picId);
            if (picture != null && picture.getFavoriteCount() != null && picture.getFavoriteCount() > 0) {
                picture.setFavoriteCount(picture.getFavoriteCount() - 1);
                pictureMapper.updateById(picture);
            }
            
            successCount.incrementAndGet();
            log.info("取消收藏成功，picId：{}", picId);
        } else if (favorite.getIsDelete() != null && favorite.getIsDelete().equals(PictureDeleteStatusEnum.IS_DELETE.getValue())) {
            // 已经取消收藏，跳过
            skipCount.incrementAndGet();
            log.info("已经取消收藏，跳过: favoriteId={}, picId={}", favorite.getId(), picId);
        } else {
            // 状态异常
            errorCount.incrementAndGet();
            log.warn("收藏状态异常: favoriteId={}, picId={}, isDelete={}", 
                    favorite.getId(), picId, favorite.getIsDelete());
        }
    }

    /**
     * 获取我的收藏图片列表，支持搜索和颜色相似度排序
     * @param userId 用户ID
     * @param pageNo 页码
     * @param pageSize 每页数量
     * @param searchText 搜索关键词（可选）
     * @param color 颜色筛选（可选，支持相似度排序）
     * @return 分页图片列表，包含点赞/收藏数
     */
    public R getMyFavoritePictureList(Long userId, Integer pageNo, Integer pageSize, String searchText, String color) {
        pageNo= pageNo==null ? 1 : pageNo;
        pageSize = pageSize==null ? 28 : pageSize;
        // 1. 查收藏表（只查未逻辑删除的）
        LambdaQueryWrapper<FavoritePicture> favoriteWrapper = new LambdaQueryWrapper<>();
        favoriteWrapper.eq(FavoritePicture::getFavoriteUserId, userId)
                .eq(FavoritePicture::getIsDelete, PictureDeleteStatusEnum.NOT_DELETE.getValue());
        List<FavoritePicture> favoriteList = favoritePictureMapper.selectList(favoriteWrapper);
        if (favoriteList.isEmpty()) {
            return ok(Collections.emptyList());
        }
        // 2. 提取所有图片ID
        List<Long> allPicIds = favoriteList.stream().map(FavoritePicture::getPicId).collect(Collectors.toList());
        // 3. 查图片表，带搜索条件
        LambdaQueryWrapper<Picture> picWrapper = new LambdaQueryWrapper<>();
        picWrapper.in(Picture::getId, allPicIds)
                .eq(Picture::getIsDelete, 0)
                .eq(Picture::getReviewStatus, 1);
        if (StringUtils.isNotBlank(searchText)) {
            picWrapper.and(w -> w.like(Picture::getName, searchText)
                    .or().like(Picture::getIntroduction, searchText));
        }
        List<Picture> pictureList = pictureMapper.selectList(picWrapper);
        if (pictureList.isEmpty()) {
            return ok(Collections.emptyList());
        }
        // 4. 颜色相似度排序（如果 color 不为空）
        List<Picture> sortedList;
        if (StringUtils.isNotBlank(color)) {
            String standardColor = ImageUtil.standardizeColorFormat(color);
            try {
                Color targetColor = Color.decode(standardColor);
                sortedList = pictureList.stream()
                        .filter(p -> StringUtils.isNotBlank(p.getPicColor()))
                        .sorted((p1, p2) -> {
                            try {
                                String c1Str = ImageUtil.standardizeColorFormat(p1.getPicColor());
                                String c2Str = ImageUtil.standardizeColorFormat(p2.getPicColor());
                                Color c1 = Color.decode(c1Str);
                                Color c2 = Color.decode(c2Str);
                                double sim1 = ImageUtil.calculateSimilarity(targetColor, c1);
                                double sim2 = ImageUtil.calculateSimilarity(targetColor, c2);
                                return Double.compare(sim2, sim1); // 降序
                            } catch (Exception e) {
                                return 0;
                            }
                        })
                        .collect(Collectors.toList());
            } catch (Exception e) {
                // 颜色格式不合法，降级为不排序
                sortedList = pictureList;
            }
        } else {
            sortedList = pictureList;
        }
        // 5. 分页
        int total = sortedList.size();
        int fromIndex = Math.max(0, (pageNo - 1) * pageSize);
        int toIndex = Math.min(total, fromIndex + pageSize);
        if (fromIndex >= toIndex) {
            return ok(Collections.emptyList());
        }
        List<Picture> pageList = sortedList.subList(fromIndex, toIndex);
        // 6. 组装VO
        List<PictureVO> voList = pageList.stream()
                .map(PictureVO::objToVo)
                .peek(vo -> {
                    Picture pic = pictureList.stream().filter(p -> p.getId().toString().equals(vo.getId())).findFirst().orElse(null);
                    if (pic != null) {
                        vo.setLikeCount(pic.getLikeCount());
                        vo.setFavoriteCount(pic.getFavoriteCount());
                    }
                })
                .collect(Collectors.toList());
        // 7. 构建分页结果
        Map<String, Object> result = new HashMap<>();
        result.put("records", voList);
        result.put("total", total);
        result.put("size", pageSize);
        result.put("current", pageNo);
        result.put("pages", (total + pageSize - 1) / pageSize);
        return ok(result);
    }
}
